/* jump_2_app.c */

#include "board_init.h"
#include "ff.h"

#include "mbedtls/entropy.h"
#include "mbedtls/ctr_drbg.h"
#include "mbedtls/md5.h"

uint8_t app_buf[4096];
uint32_t * vtor;

void jump_to_app(void)
{
    /* init fatfs. */
    FATFS app_fs;
    if (FR_OK == f_mount(&app_fs, "0:/", 1))
    {
    }

    FIL file;

    /* open bin file. */
    if (FR_OK == f_open(&file, "0:/"BOARD_APP_NAME, FA_READ) )
    {
        /* calc md5. */
        mbedtls_md5_context md5_ctx;

        mbedtls_md5_init(&md5_ctx);
        mbedtls_md5_starts(&md5_ctx);

        while(1)
        {
            UINT br = 0;
            f_read(&file, app_buf, sizeof(app_buf), &br);

            mbedtls_md5_update(&md5_ctx, app_buf, br);

            if (br < sizeof(app_buf))
            {
                break;
            }
        }

        f_lseek(&file, 0);
        uint8_t md5_val[16] = {0};
        mbedtls_md5_finish(&md5_ctx, md5_val);

        /* check md5, the md5 length is 16 byte. */
        if (memcmp((uint8_t*)BOARD_MD5_BASE, md5_val, sizeof(md5_val)) != 0)
        {
            /* new file, update. */
            BOARD_EraseSector4KB(BOARD_MD5_BASE);

            uint32_t has_write = 0;
            while(1)
            {
                UINT br = 0;
                memset(app_buf, 0xff, sizeof(app_buf));
                f_read(&file, app_buf, sizeof(app_buf), &br);

                BOARD_EraseSector4KB(has_write);
                BOARD_WriteSector4KB(has_write, app_buf);
                has_write+=4096;

                if (br < sizeof(app_buf))
                {
                    break;
                }
            }

            /* write new md5. */
            memset(app_buf, 0xff, sizeof(app_buf));
            memcpy(app_buf, md5_val, sizeof(md5_val));
            BOARD_WriteSector4KB(BOARD_MD5_BASE, app_buf);
        }
    }
    else
    {
    }

    /* close fatfs. */
    f_unmount("0:/");

    /* jump to app. */
    CLOCK_ResetToDefault();

    vtor = (uint32_t *)BOARD_APP_BASE;

    __disable_irq();
    SCB->VTOR = BOARD_APP_BASE;

    __ISB();
    __DSB();

    __set_MSP(vtor[0]);
    __set_PSP(vtor[0]);

    __enable_irq();
    ((void(*)(void))vtor[1])();

}

/* EOF. */
